home *** CD-ROM | disk | FTP | other *** search
- #! /bin/sh
- #
- # Laptop mode tools module: core laptop mode functionality
- #
-
-
-
-
- # Remove an option (the first parameter) of the form option=<number> from
- # a mount options string (the rest of the parameters).
- remove_numeric_mount_option () {
- OPT="$1"
- shift
- echo ",$*," | sed \
- -e 's|,'"$OPT"'=[0-9]*,|,|g' \
- -e 's/,,*/,/g' \
- -e 's/^,//' \
- -e 's/,$//'
- }
-
- # Remove an option (the first parameter) without any arguments from
- # a mount option string (the rest of the parameters).
- remove_fixed_mount_option () {
- OPT="$1"
- shift
- echo ",$*," | sed \
- -e 's|,'"$OPT"',|,|g' \
- -e 's/,,*/,/g' \
- -e 's/^,//' \
- -e 's/,$//'
- }
-
- # Find out the state of an atime option ("atime"/"noatime"/"relatime"/"norelatime")
- # in a set of mount options, and use this state to replace the value of the
- # option in another mount options string.
- #
- # Example:
- # replace_atime_mount_option defaults,user=1000,atime defaults,noatime
- #
- # This yields "defaults,atime".
- replace_atime_mount_option () {
- REPLACEMENT_OPTS="$1"
- OPTS="$2"
- PARSEDOPTS="$(remove_fixed_mount_option atime $OPTS)"
- PARSEDOPTS="$(remove_fixed_mount_option noatime $PARSEDOPTS)"
- PARSEDOPTS="$(remove_fixed_mount_option relatime $PARSEDOPTS)"
- PARSEDOPTS="$(remove_fixed_mount_option norelatime $PARSEDOPTS)"
-
- case ",$REPLACEMENT_OPTS," in
- *",relatime,"*)
- echo "$PARSEDOPTS,relatime"
- ;;
- *",noatime,"*)
- echo "$PARSEDOPTS,noatime"
- ;;
- *)
- # Kind of strange: to go from relatime to atime, we have to
- # explicitly specify norelatime.
- echo "$PARSEDOPTS,atime,norelatime"
- ;;
- esac
- }
-
- # Find out the state of a numbered option (e.g. "commit=NNN") in
- # a set of options, and use this state to replace the
- # value of the option in another mount options string.
- #
- # Example:
- # replace_numeric_mount_option commit defaults,user=1000,commit=3 defaults,commit=7
- #
- # This example yields "defaults,commit=3".
- replace_numeric_mount_option () {
- OPT="$1"
- DEF_OPT="$2"
- REPLACEMENT_OPTS="$3"
- OPTS="$4"
- PARSEDOPTS="$(remove_numeric_mount_option $OPT $OPTS)"
-
- if echo ",$REPLACEMENT_OPTS," | grep ",$OPT=[0123456789]+," > /dev/null ; then
- echo -n "$PARSEDOPTS,$OPT="
- echo ",$REPLACEMENT_OPTS," | sed \
- -e 's/.*,'"$OPT"'=//' \
- -e 's/,.*//'
- else
- # Option not present in REPLACEMENT_OPTS: use the default.
- echo "$PARSEDOPTS,$DEF_OPT"
- fi
- }
-
- deduce_fstype () {
- MP="$1"
- # My root filesystem unfortunately has type "unknown" in
- # /etc/mtab. If we encounter "unknown", we try to get the
- # type from fstab. This still might be wrong, in which
- # case the code further down will issue a big warning.
- sed 's/[[:space:]]*#.*$//' /etc/fstab |
- while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do
- if [ "$FSTAB_MP" = "$MP" ]; then
- echo "$FSTAB_FST"
- exit 0
- fi
- done
- }
-
-
- #
- # Set kernel setting, showing an error if this fails.
- #
- # Parameter 1: sysctl/proc path
- # Parameter 2: the value
- #
- set_sysctl() {
- $LM_VERBOSE && echo "Executing: echo $2 > $1" >> $OUTPUT
- if ! echo "$2" > "$1" ; then
- echo "SETTING OF KERNEL PARAMETER FAILED: echo $2 \> $1"
- fi
- }
-
-
- if [ "$CONTROL_READAHEAD" -ne 0 ] ; then
- if /sbin/blockdev --help 2>&1 | grep -Fq -- '--setfra' ; then
- READAHEAD_OPTION=--setfra
- else
- READAHEAD_OPTION=--setra
- if [ "$KLEVEL" = "2.4" ] ; then
- echo "Warning: Running a 2.4 kernel with blockdev that does not support --setfra."
- echo "File system readahead will not function properly."
- fi
- fi
- fi
-
-
-
- if [ $CONTROL_NOATIME -eq 1 ] ; then
- if [ "$KLEVEL" = "2.4" ] ; then
- $LM_VERBOSE && echo "Relatime is not supported on 2.4 kernels. Using noatime instead" >> $OUTPUT
- USE_RELATIME=0
- elif [ "$KLEVEL" = "2.6" -a "$KMINOR" -lt 23 ] ; then
- $LM_VERBOSE && echo "Relatime is not supported on kernels before 2.6.23. Using noatime instead." >> $OUTPUT
- USE_RELATIME=0
- fi
- if [ "$USE_RELATIME" = 1 ] ; then
- NOATIME_OPT=",relatime"
- else
- NOATIME_OPT=",noatime"
- fi
- fi
-
-
- # Adjust kernel settings and mount options (but only if data loss
- # sensitive features are active)
- if [ "$ACTIVATE_WITH_POSSIBLE_DATA_LOSS" -eq 1 ] ; then
- # Take MAX_LOST_WORK_SECONDS from LM_BATT_MAX_LOST_WORK_SECONDS or LM_AC_MAX_LOST_WORK_SECONDS_WITH_LM, depending on power state.
- MAX_LOST_WORK_SECONDS=$LM_BATT_MAX_LOST_WORK_SECONDS
- if [ $ON_AC -eq 1 ] ; then
- MAX_LOST_WORK_SECONDS=$LM_AC_MAX_LOST_WORK_SECONDS
- fi
-
- AGE=$((100*$MAX_LOST_WORK_SECONDS))
- XFS_AGE=$(($XFS_HZ*$MAX_LOST_WORK_SECONDS))
-
- if [ -d /proc/sys/vm/pagebuf ] ; then
- # (For 2.4 and early 2.6.)
- # This only needs to be set, not reset -- it is only used when
- # laptop mode is enabled.
- $LM_VERBOSE && echo "Adjusting XFS kernel parameters for 2.4 and early 2.6 kernels." >> $OUTPUT
- set_sysctl /proc/sys/vm/pagebuf/lm_flush_age $XFS_AGE
- set_sysctl /proc/sys/fs/xfs/lm_sync_interval $XFS_AGE
- elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
- # (A couple of early 2.6 laptop mode patches had these.)
- # This only needs to be set, not reset -- it is only used when
- # laptop mode is enabled.
- $LM_VERBOSE && echo "Adjusting XFS kernel parameters for early patched 2.6 kernels." >> $OUTPUT
- set_sysctl /proc/sys/fs/xfs/lm_age_buffer $XFS_AGE
- set_sysctl /proc/sys/fs/xfs/lm_sync_interval $XFS_AGE
- elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then
- # (2.6.6)
- # But not for these -- they are also used in normal
- # operation.
- $LM_VERBOSE && echo "Adjusting XFS kernel parameters for 2.6.6 kernel." >> $OUTPUT
- set_sysctl /proc/sys/fs/xfs/age_buffer $XFS_AGE
- set_sysctl /proc/sys/fs/xfs/sync_interval $XFS_AGE
- elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
- # (2.6.7 upwards)
- # And not for these either. These are in centisecs,
- # not USER_HZ, so we have to use $AGE, not $XFS_AGE.
- $LM_VERBOSE && echo "Adjusting XFS kernel parameters for >2.6.7 kernel." >> $OUTPUT
- set_sysctl /proc/sys/fs/xfs/age_buffer_centisecs $AGE
- set_sysctl /proc/sys/fs/xfs/xfssyncd_centisecs $AGE
- set_sysctl /proc/sys/fs/xfs/xfsbufd_centisecs 3000
- fi
-
- case "$KLEVEL" in
- "2.4")
- $LM_VERBOSE && echo "Adjusting 2.4 kernel parameters to enable laptop mode." >> $OUTPUT
- set_sysctl /proc/sys/vm/laptop_mode 1
- set_sysctl /proc/sys/vm/bdflush "30 500 0 0 $AGE $AGE 60 20 0"
- ;;
- "2.6")
- $LM_VERBOSE && echo "Adjusting 2.6 kernel parameters to enable laptop mode." >> $OUTPUT
- set_sysctl /proc/sys/vm/laptop_mode "$LM_SECONDS_BEFORE_SYNC"
- set_sysctl /proc/sys/vm/dirty_writeback_centisecs "$AGE"
- set_sysctl /proc/sys/vm/dirty_expire_centisecs "$AGE"
- set_sysctl /proc/sys/vm/dirty_ratio "$LM_DIRTY_RATIO"
- set_sysctl /proc/sys/vm/dirty_background_ratio "$LM_DIRTY_BACKGROUND_RATIO"
- ;;
- esac
- if [ $CONTROL_MOUNT_OPTIONS -eq 1 ]; then
- $LM_VERBOSE && echo "Remounting filesystems." >> $OUTPUT
- cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
- case "$FST" in
- rootfs|unionfs|tmpfs|squashfs|sysfs|usbfs|proc|devpts)
- continue
- ;;
- esac
-
- DO=0
-
- case " $PARTITIONS " in
- *" $DEV "*)
- DO=1
- $LM_VERBOSE && echo "$DEV found in PARTITIONS." >> $OUTPUT
- ;;
- *)
- $LM_VERBOSE && echo "$DEV not found in PARTITIONS." >> $OUTPUT
- ;;
- esac
- case " $PARTITIONS " in
- *" $MP "*)
- DO=1
- $LM_VERBOSE && echo "$MP found in PARTITIONS." >> $OUTPUT
- ;;
- *)
- $LM_VERBOSE && echo "$MP not found in PARTITIONS." >> $OUTPUT
- esac
- case " $PARTITIONS " in
- *" auto "*)
- $LM_VERBOSE && echo "Checking $DEV against HD because PARTITIONS contains \"auto\"." >> $OUTPUT
- for THISHD in $HD ; do
- $LM_VERBOSE && echo " Considering $THISHD." >> $OUTPUT
- case " $DEV" in *"$THISHD"*)
- DO=1
- $LM_VERBOSE && echo " $DEV contains $THISHD, which is in HD, so we will remount it." >> $OUTPUT
- break
- ;;
- esac
- done
- ;;
- esac
- if [ "$DO" -ne 0 ] ; then
- $LM_VERBOSE && echo "Original options: $OPTS" >> $OUTPUT
- if [ "$WAS_ACTIVE" -eq 0 ] ; then
- # Coming from inactive state: save last known mount options for the device.
- $LM_VERBOSE && echo "Updating /var/run/laptop-mode-tools/nolm-mountopts." >> $OUTPUT
- if [ -f /var/run/laptop-mode-tools/nolm-mountopts ] ; then
- sed -i "s|^$DEV .*$||" /var/run/laptop-mode-tools/nolm-mountopts
- fi
- echo $DEV $OPTS >> /var/run/laptop-mode-tools/nolm-mountopts
- else
- $LM_VERBOSE && echo "Not updating /var/run/laptop-mode-tools/nolm-mountopts because laptop mode was already active." >> $OUTPUT
- fi
- if [ "$FST" = 'unknown' ]; then
- $LM_VERBOSE && echo "Deducing fstype for $MP." >> $OUTPUT
- FST=$(deduce_fstype $MP)
- $LM_VERBOSE && echo "Deduced fstype for $MP as $FST." >> $OUTPUT
- fi
- # Strip stuff like ext3,ext2 into just ext3.
- $LM_VERBOSE && echo "Reducing file system type." >> $OUTPUT
- FST=${FST%%,*}
- case "$FST" in
- "ext3"|"reiserfs"|"ext4dev"|"ext4")
- $LM_VERBOSE && echo "Removing commit mount option from original options." >> $OUTPUT
- PARSEDOPTS="$(remove_numeric_mount_option commit "$OPTS")"
- $LM_VERBOSE && echo "Executing: mount $DEV $MP -t $FST -o remount,$PARSEDOPTS,commit=$MAX_LOST_WORK_SECONDS$NOATIME_OPT" >> $OUTPUT
- if (! mount $DEV $MP -t $FST -o remount,$PARSEDOPTS,commit=$MAX_LOST_WORK_SECONDS$NOATIME_OPT) ; then
- if [ "$FST" = "ext3" -a "$MP" = "/" ] ; then
- echo "BIG FAT WARNING: Your root filesystem mounted as ext3 seems to lack support for"
- echo "the commit mount option. This usually means that your root filesystem is"
- echo "mounted as ext2 because there is no ext3 support in the kernel at boot time,"
- echo "usually because you compiled ext3 as a module and don't load it in an initrd."
- echo "Note that on recent 2.6 kernels, /proc/mounts shows the correct fs type for"
- echo "the device /dev/root. You can check your actual root filesystem mount type"
- echo "there. To fix the problem, either make ext3 available at boot time by compiling"
- echo "it statically into the kernel, or configure the correct filesystem type in"
- echo "/etc/fstab."
- fi
- fi
- ;;
- *)
- $LM_VERBOSE && echo "Executing: mount $DEV $MP -t $FST -o remount,$OPTS$NOATIME_OPT" >> $OUTPUT
- mount $DEV $MP -t $FST -o remount,$OPTS$NOATIME_OPT
- ;;
- esac
- if [ -b $DEV -a "$CONTROL_READAHEAD" -ne 0 ] ; then
- $LM_VERBOSE && echo "Executing: /sbin/blockdev $READAHEAD_OPTION $(($LM_READAHEAD * 2)) $DEV" >> $OUTPUT
- /sbin/blockdev $READAHEAD_OPTION $(($LM_READAHEAD * 2)) $DEV >> $OUTPUT 2>&1
- fi
- fi
- done
- fi
- else
- # DEACTIVATE w.r.t. kernel options and mount point settings
- U_AGE=$((100*$DEF_UPDATE))
- B_AGE=$((100*$DEF_MAX_AGE))
- set_sysctl /proc/sys/vm/laptop_mode 0
- if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
- # These need to be restored, if there are no lm_*.
- $LM_VERBOSE && echo "Restoring default XFS settings (pre-centisecs version)." >> $OUTPUT
- set_sysctl /proc/sys/fs/xfs/age_buffer $(($XFS_HZ*$DEF_XFS_AGE_BUFFER))
- set_sysctl /proc/sys/fs/xfs/sync_interval $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL))
- elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
- # These need to be restored as well.
- $LM_VERBOSE && echo "Restoring default XFS settings." >> $OUTPUT
- set_sysctl /proc/sys/fs/xfs/age_buffer_centisecs $((100*$DEF_XFS_AGE_BUFFER))
- set_sysctl /proc/sys/fs/xfs/xfssyncd_centisecs $((100*$DEF_XFS_SYNC_INTERVAL))
- set_sysctl /proc/sys/fs/xfs/xfsbufd_centisecs $((100*$DEF_XFS_BUFD_INTERVAL))
- fi
- case "$KLEVEL" in
- "2.4")
- $LM_VERBOSE && echo "Adjusting 2.4 kernel parameters to disable laptop mode." >> $OUTPUT
- set_sysctl /proc/sys/vm/bdflush "30 500 0 0 $U_AGE $B_AGE 60 20 0"
- ;;
- "2.6")
- $LM_VERBOSE && echo "Adjusting 2.6 kernel parameters to disable laptop mode." >> $OUTPUT
- set_sysctl /proc/sys/vm/dirty_writeback_centisecs "$U_AGE"
- set_sysctl /proc/sys/vm/dirty_expire_centisecs "$B_AGE"
- set_sysctl /proc/sys/vm/dirty_ratio "$NOLM_DIRTY_RATIO"
- set_sysctl /proc/sys/vm/dirty_background_ratio "$NOLM_DIRTY_BACKGROUND_RATIO"
- ;;
- esac
- if [ $CONTROL_MOUNT_OPTIONS -eq 1 ] ; then
- $LM_VERBOSE && echo "Remounting filesystems." >> $OUTPUT
- cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
- DO=0
- case " $PARTITIONS " in
- *" $DEV "*)
- DO=1
- $LM_VERBOSE && echo "$DEV found in PARTITIONS." >> $OUTPUT
- ;;
- *)
- $LM_VERBOSE && echo "$DEV not found in PARTITIONS." >> $OUTPUT
- ;;
- esac
- case " $PARTITIONS " in
- *" $MP "*)
- DO=1
- $LM_VERBOSE && echo "$MP found in PARTITIONS." >> $OUTPUT
- ;;
- *)
- $LM_VERBOSE && echo "$MP not found in PARTITIONS." >> $OUTPUT
- ;;
- esac
- case " $PARTITIONS " in
- *" auto "*)
- $LM_VERBOSE && echo "Checking $DEV against HD because PARTITIONS contains \"auto\"." >> $OUTPUT
- for THISHD in $HD ; do
- $LM_VERBOSE && echo " Considering $THISHD." >> $OUTPUT
- case " $DEV" in *"$THISHD"*)
- DO=1
- $LM_VERBOSE && echo " $DEV contains $THISHD, which is in HD, so we will remount it." >> $OUTPUT
- break
- ;;
- esac
- done
- ;;
- esac
- if [ "$DO" -ne 0 ] ; then
- # Reset commit and atime options to defaults.
- $LM_VERBOSE && echo "Original options: $OPTS" >> $OUTPUT
- if [ "$FST" = 'unknown' ]; then
- $LM_VERBOSE && echo "Deducing fstype for $MP." >> $OUTPUT
- FST=$(deduce_fstype $MP)
- $LM_VERBOSE && echo "Deduced fstype for $MP as $FST." >> $OUTPUT
- fi
-
- # Strip stuff like ext3,ext2 into just ext3.
- $LM_VERBOSE && echo "Reducing file system type." >> $OUTPUT
- FST=${FST%%,*}
-
- # Retrieve original non-laptop mode mount options and restore them.
- # If the file that stores them doesn't exist, then laptop mode
- # has never been started.
- if [ "$WAS_ACTIVE" -ne 0 -a -f /var/run/laptop-mode-tools/nolm-mountopts ] ; then
- SAVED_OPTS=`grep "^$DEV " /var/run/laptop-mode-tools/nolm-mountopts`
- SAVED_OPTS=${SAVED_OPTS#* } # trim device name
-
- case "$FST" in
- "ext3"|"reiserfs"|"ext4dev"|"ext4")
- PARSEDOPTS="$(replace_numeric_mount_option commit commit=0 $SAVED_OPTS $OPTS)"
- PARSEDOPTS="$(replace_atime_mount_option $SAVED_OPTS $PARSEDOPTS)"
- $LM_VERBOSE && echo "Executing: mount $DEV $MP -t $FST -o remount,$PARSEDOPTS" >> $OUTPUT
- mount $DEV $MP -t $FST -o remount,$PARSEDOPTS
- ;;
- *)
- PARSEDOPTS="$(replace_atime_mount_option $SAVED_OPTS $OPTS)"
- $LM_VERBOSE && echo "Executing: mount $DEV $MP -t $FST -o remount,$PARSEDOPTS" >> $OUTPUT
- mount $DEV $MP -t $FST -o remount,$PARSEDOPTS
- ;;
- esac
- else
- $LM_VERBOSE && echo "No saved mount options, so apparently we never remounted this filesystem during this session." >> $OUTPUT
- $LM_VERBOSE && echo "Not remounting." >> $OUTPUT
- fi
- if [ -b $DEV -a "$CONTROL_READAHEAD" -ne 0 ] ; then
- $LM_VERBOSE && echo "Executing: /sbin/blockdev $READAHEAD_OPTION $(($NOLM_READAHEAD * 2)) $DEV" >> $OUTPUT
- /sbin/blockdev $READAHEAD_OPTION $(($NOLM_READAHEAD * 2)) $DEV >> $OUTPUT 2>&1
- fi
- fi
- done
- fi
- fi
-
-